package com.pzr.soccer.crawler.util;

import com.pzr.soccer.match.domain.Game;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class ScanGameHelper {
 public static final  String Dangerous_Home="dangerous_home";
    public static final  String Dangerous_Away="dangerous_away";
    public static final  String Off_Home="off_home";
    public static final  String Off_Away="off_away";
    public static final  String On_Home="on_home";
    public static final  String On_Away="on_away";
    public static final  String All_Attack="all_attack";

    public static final  String Pair_Name_Score="map_name_Score";
    public static final  String Pair_Name_Corner="map_name_Corner";
    public static final  String Pair_Name_Shot="map_name_Shot";
    public static final  String Pair_Name_Danger="map_name_Danger";

    public static String extract(String contentText,String key){

        Pattern pattern = Pattern.compile("(" + key + "\\s+=\\s+)(.*\\]);??");
        Matcher matcher = pattern.matcher(contentText);
        if (matcher.find()) {
            String group2 = matcher.group(2);
            return group2;
        }
        return "";
    }


    public static NavigableMap<Integer, List<Integer>> getPairShot(String pageStr) {

        NavigableMap<Integer, Integer> home = getTotalShots(extract(pageStr,Off_Home), extract(pageStr,On_Home));
        NavigableMap<Integer, Integer> away = getTotalShots(extract(pageStr,Off_Away), extract(pageStr,On_Away));
        NavigableMap<Integer, List<Integer>> map = new TreeMap<>();
        int curHome = 0;
        int curAway = 0;
        for (int i = 1; i < 125; i++) {
            List<Integer> list=new ArrayList<>();

            int curHome1 = home.get(i) != null ? home.get(i) : curHome;
            int curAway1 = away.get(i) != null ? away.get(i) : curAway;
            if (curHome1 + curAway1 == curHome + curAway) {
                continue;
            } else {
                curAway = curAway1;
                curHome = curHome1;
            }
            list.add(curHome);
            list.add(curAway);
            map.put(i, list);
        }
        return map;
    }

    public static NavigableMap<Integer, List<Integer>> getPairCorner( String pageStr) {
        NavigableMap<Integer, List<Integer>> map = new TreeMap<>();
        Pattern pattern = Pattern.compile("\\{.*?\\}\\}");
        String info=extract(pageStr,All_Attack);
        int home_corner = 0, away_corner = 0;
            Matcher matcher = pattern.matcher(info);
        while (matcher.find()) {
            String sub = info.substring(matcher.start(), matcher.end());
            Pattern pattern2 = Pattern.compile(".*x\"\\:(\\d+)(.*)");
            Matcher matcher2 = pattern2.matcher(sub);
            if (matcher2.matches()) {
                Integer curMin = Integer.valueOf(matcher2.group(1));
                List<Integer> list=new ArrayList<>();
                if (sub.contains("corner_h")) {
                    home_corner++;
                    map.put(curMin, getAMutableList(home_corner,away_corner));
                } else if (sub.contains("corner_a")) {
                    away_corner++;
                    map.put(curMin, getAMutableList(home_corner,away_corner));
                }

            }
        }
        return map;
    }

    public static NavigableMap<Integer, List<Integer>> getPairScore(String pageStr) {
        NavigableMap<Integer, List<Integer>> map = new TreeMap<>();
        String info=extract(pageStr,All_Attack);
        Pattern pattern = Pattern.compile("\\{.*?\\}\\}");
        int home_goal = 0, away_goal = 0;
        Matcher matcher = pattern.matcher(info);
        while (matcher.find()) {
            String sub = info.substring(matcher.start(), matcher.end());
            Pattern pattern2 = Pattern.compile(".*x\"\\:(\\d+)(.*)");
            Matcher matcher2 = pattern2.matcher(sub);
            if (matcher2.matches()) {
                Integer curMin = Integer.valueOf(matcher2.group(1));
                if (sub.contains("goal_h") || sub.contains("goal_small")) {
                    home_goal++;
                    map.put(curMin, getAMutableList(home_goal, away_goal));
                } else if (sub.contains("goal_a")) {
                    away_goal++;
                    map.put(curMin, getAMutableList(home_goal, away_goal));
                }

            }

        }
        return map;
    }

    public static NavigableMap<Integer, List<Integer>> mergeDangersToMap(String pageStr) {

        NavigableMap<Integer, Integer> homeDangerous = new TreeMap<>();
        NavigableMap<Integer, Integer> awayDangerous = new TreeMap<>();
        NavigableMap<Integer, List<Integer>> map = new TreeMap<>();
        String info_d_h=extract(pageStr,Dangerous_Home);
        String info_d_a=extract(pageStr,Dangerous_Away);
        Pattern pattern = Pattern.compile("(\\d+\\,\\d+)");
        Matcher m1 = pattern.matcher(info_d_h), m2 = pattern.matcher(info_d_a);

        while (m1.find()) {
            String sub = info_d_h.substring(m1.start(), m1.end());
            String[] subs = sub.split(",");
            homeDangerous.put(Integer.valueOf(subs[0]), Integer.valueOf(subs[1]));
        }

        while (m2.find()) {
            String sub = info_d_a.substring(m2.start(), m2.end());
            String[] subs = sub.split(",");
            awayDangerous.put(Integer.valueOf(subs[0]), Integer.valueOf(subs[1]));
        }

        int curHome = 0, curAway = 0;
        for (int i = 1; i < 125; i++) {

            int curHome1 = homeDangerous.get(i) != null ? homeDangerous.get(i) : curHome;
            int curAway1 = awayDangerous.get(i) != null ? awayDangerous.get(i) : curAway;
            if (curHome1 + curAway1 == curHome + curAway) {
                continue;
            } else {
                curAway = curAway1;
                curHome = curHome1;
            }
            map.put(i, getAMutableList(curHome, curAway));
        }

        return map;
    }
    public static NavigableMap<Integer, Integer> getTotalShots(String onShots, String offShots) {
        Pattern pattern = Pattern.compile("(\\d+\\,\\d+)");
        Matcher m = pattern.matcher(offShots);

        List<String> shots = new ArrayList<>();
        while (m.find()) {
            String sub = (offShots).substring(m.start(), m.end());
            shots.add(sub + ",off");
        }

        Matcher m2 = pattern.matcher(onShots);
        while (m2.find()) {
            String sub = (onShots).substring(m2.start(), m2.end());
            shots.add(sub + ",on");
        }

        shots.sort((o1, o2) -> {
            String[] o1str = o1.split(",");
            int o1num = Integer.valueOf(o1str[0]);
            String[] o2str = o2.split(",");
            int o2num = Integer.valueOf(o2str[0]);

            return o1num - o2num;
        });

        NavigableMap<Integer, Integer> totalShots = new TreeMap<>();
        int curOff = 0, curOn = 0;
        for (String str : shots) {
            if (str.contains("off")) {
                curOff = Integer.valueOf(str.split(",")[1]);
            } else {
                curOn = Integer.valueOf(str.split(",")[1]);
            }
            totalShots.put(Integer.valueOf(str.split(",")[0]), curOff + curOn);

        }

        return totalShots;
    }

    public static LinkedHashMap<String, List<Integer>> navigableMap2LinkedMap(NavigableMap<Integer, List<Integer>> nMap) {
        LinkedHashMap<String, List<Integer>> lMap = new LinkedHashMap<>();

        for (Map.Entry<Integer, List<Integer>> entry : nMap.entrySet()) {
            if (entry.getKey() <= 46) {

                lMap.put("f_" + String.valueOf(entry.getKey()), entry.getValue());
            } else {
                lMap.put("s_" + String.valueOf(entry.getKey()), entry.getValue());
            }

        }
        return lMap;
    }

    public static NavigableMap<Integer, int[]> navigableMap2NaviIntMap(NavigableMap<Integer, List<Integer>> nMap) {
        NavigableMap<Integer, int[]> naviMap = new TreeMap<>();

        for (Map.Entry<Integer, List<Integer>> entry : nMap.entrySet()) {
             int[] arr=new int[2];
             arr[0]=entry.getValue().get(0);
             arr[1]=entry.getValue().get(1);

            if (entry.getKey() <= 46) {

                naviMap.put(entry.getKey(),arr);
            } else {
                naviMap.put(entry.getKey()+100,arr);
            }

        }
        return naviMap;
    }



    public static LinkedHashMap<String, List<Integer>> getPairMapFromPageStr(String pageStr,String pairName){
         switch (pairName){
             case Pair_Name_Score:return navigableMap2LinkedMap(getPairScore(pageStr)) ;
             case Pair_Name_Corner:return navigableMap2LinkedMap(getPairCorner(pageStr)) ;
             case Pair_Name_Shot:return  navigableMap2LinkedMap(getPairShot(pageStr)) ;
             case Pair_Name_Danger: return navigableMap2LinkedMap(mergeDangersToMap(pageStr)) ;
             default:log.warn("no such map name :"+pairName);return  null;
         }

    }

    public static NavigableMap<Integer, int[]> getPairNaviMapFromPageStr(String pageStr,String pairName){
        switch (pairName){
            case Pair_Name_Score:return navigableMap2NaviIntMap(getPairScore(pageStr)) ;
            case Pair_Name_Corner:return navigableMap2NaviIntMap(getPairCorner(pageStr)) ;
            case Pair_Name_Shot:return  navigableMap2NaviIntMap(getPairShot(pageStr)) ;
            case Pair_Name_Danger: return navigableMap2NaviIntMap(mergeDangersToMap(pageStr)) ;
            default:log.warn("no such map name :"+pairName);return  null;
        }

    }


    public static  void setGameInitPairMap(Game game, String pageStr){

        game.setPairScore(getPairNaviMapFromPageStr(pageStr,Pair_Name_Score));
        game.setPairCorner(getPairNaviMapFromPageStr(pageStr,Pair_Name_Corner));
        game.setPairShot(getPairNaviMapFromPageStr(pageStr,Pair_Name_Shot));
        game.setPairDanger(getPairNaviMapFromPageStr(pageStr,Pair_Name_Danger));
    }

    private static  List<Integer> getAMutableList(int a,int b){

          List<Integer> list=new ArrayList<>();
          list.add(a);
          list.add(b);
          return  list;
    }


}


